home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / src / haeberli / tools / clock.c < prev    next >
C/C++ Source or Header  |  1994-08-01  |  12KB  |  620 lines

  1. /*
  2.  * Copyright 1991, 1992, 1993, 1994, Silicon Graphics, Inc.
  3.  * All Rights Reserved.
  4.  *
  5.  * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
  6.  * the contents of this file may not be disclosed to third parties, copied or
  7.  * duplicated in any form, in whole or in part, without the prior written
  8.  * permission of Silicon Graphics, Inc.
  9.  *
  10.  * RESTRICTED RIGHTS LEGEND:
  11.  * Use, duplication or disclosure by the Government is subject to restrictions
  12.  * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
  13.  * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
  14.  * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
  15.  * rights reserved under the Copyright Laws of the United States.
  16.  */
  17. /*
  18.  *    clock - 
  19.  *        A simple desk clock.
  20.  *
  21.  *                Paul Haeberli - 1984
  22.  *
  23.  *        Antialiased version for VGX and beyond
  24.  *
  25.  *                Kurt Akeley - 1991
  26.  */
  27.  
  28. #include <stdio.h>
  29. #include <time.h>
  30. #include <gl/gl.h>
  31. #include <gl/device.h>
  32. #include <math.h>
  33.  
  34. typedef struct XY {
  35.     float x;
  36.     float y;
  37. } XY;
  38.  
  39. int hours, minutes, seconds;
  40. int ahour, aminute, alarmflag;
  41. XY sechand[4]; 
  42. XY minhand[4]; 
  43. XY hourhand[4]; 
  44. XY alrmhand[4];
  45. int menu;
  46. int dodot;
  47. int doaa;
  48. int iconic;
  49. long width, height;
  50. long xoffset, yoffset;
  51.  
  52. Matrix ident = {1, 0, 0, 0,
  53.          0, 1, 0, 0,
  54.          0, 0, 1, 0,
  55.          0, 0, 0, 1
  56. };
  57.  
  58. #define greyindex(x) (32 + (int)(25*x))
  59. #define setgrey(x) setcolor(greyindex(x))
  60. #define ANGCONV 1.90985931
  61.  
  62. void setalarmangle(long mousex,long mousey);
  63. int shouldbeep();
  64. void makeface();
  65. void showhands(int fillcolor,int bordercolor,int shadow);
  66. void gettime(int * h,int * m,int * s);
  67. void setcolor(int c);
  68. void drawpoly2(long verts,XY* v);
  69. void drawpolf2(long verts,XY* v);
  70. void drawcircle(float radius);
  71.  
  72. void drawcircle(float radius);
  73.  
  74. XY
  75. xy(double x, double y)
  76. {
  77.      XY a;
  78.      a.x = x;
  79.      a.y = y;
  80.      return a;
  81. }
  82.  
  83.  
  84. main(int argc,char **argv,char **envp)
  85. {
  86.     int i;
  87.     short t, val;
  88.     int leftdown;
  89.     int draw_needed;
  90.     int mousex,mousey;
  91.  
  92.     /* check if resources are available */
  93.     if (getgdesc(GD_POLYSMOOTH) && argc < 3)
  94.     doaa = TRUE;
  95.     else
  96.     doaa = FALSE;
  97.  
  98.     alarmflag=0;
  99.     if (argc>1)
  100.     dodot = 1;
  101.  
  102.     /* get a window */ 
  103.     iconsize(85, 66);
  104.     keepaspect(1,1);
  105.     if (doaa) {
  106.     winopen("aaclock");
  107.     RGBmode();
  108.     doublebuffer();
  109.     gconfig();
  110.     } else {
  111.     winopen("clock");
  112.     }
  113.     glcompat(GLC_OLDPOLYGON,FALSE);    /* just for the circle */
  114.     subpixel(TRUE);
  115.     mmode(MVIEWING);
  116.     menu = defpup("clock %t|calendar|alarm");
  117.     setpup(menu, 2, PUP_BOX);
  118.     noise(TIMER0,getgdesc(GD_TIMERHZ));
  119.     qdevice(TIMER0);
  120.     qdevice(MENUBUTTON);
  121.     qdevice(LEFTMOUSE);
  122.     qdevice(ESCKEY);
  123.     qdevice(REDRAWICONIC);
  124.     qdevice(WINFREEZE);
  125.     qdevice(WINTHAW);
  126.  
  127.     /* make the hands */
  128.     hourhand[0] = minhand[0] = xy(-0.5,0.0);
  129.     hourhand[1] = minhand[1] = xy(0.0,-1.5);
  130.     hourhand[2] = minhand[2] = xy( 0.5,0.0);
  131.  
  132.     minhand[3] = xy(0.0,11.5);
  133.     hourhand[3] = xy(0.0,7.0);
  134.  
  135.     sechand[0] = xy(-0.05,0.0);
  136.     sechand[1] = xy(0.0,-2.0);
  137.     sechand[2] = xy( 0.05,0.0);
  138.     sechand[3] = xy(0.0,11.5);
  139.  
  140.     alrmhand[0] = xy(-0.2,0.0);
  141.     alrmhand[1] = xy(0.0,-1.0);
  142.     alrmhand[2] = xy( 0.2,0.0);
  143.     alrmhand[3] = xy(0.0,9.0);
  144.  
  145.     /* draw the clock */
  146.     qenter(REDRAW,1);
  147.     while (1) {
  148.     /* always empty queue before drawing, then draw only when required */
  149.     while (qtest() || !draw_needed) {
  150.         switch (t = qread(&val)) {
  151.         case REDRAW:
  152.         case REDRAWICONIC:
  153.             iconic = t == REDRAWICONIC;
  154.             getsize(&width,&height);
  155.             getorigin(&xoffset,&yoffset);
  156.             viewport(0,width-1,0,height-1);
  157.             draw_needed = TRUE;
  158.             break;
  159.         case ESCKEY:
  160.             if (!val)
  161.             exit(0);
  162.             break;
  163.         case TIMER0:
  164.             draw_needed = TRUE;
  165.             break;
  166.         case LEFTMOUSE:
  167.             leftdown = val;
  168.             if (alarmflag) {
  169.             if (leftdown) {
  170.                 qdevice(MOUSEX);
  171.                 qdevice(MOUSEY);
  172.                 mousex = getvaluator(MOUSEX);
  173.                 mousey = getvaluator(MOUSEY);
  174.             } else {
  175.                 unqdevice(MOUSEX);
  176.                 unqdevice(MOUSEY);
  177.             }
  178.             draw_needed = TRUE;
  179.             }
  180.             break;
  181.         case MOUSEX:
  182.             mousex = val;
  183.             draw_needed = TRUE;
  184.             break;
  185.         case MOUSEY:
  186.             mousey = val;
  187.             draw_needed = TRUE;
  188.             break;
  189.         case MENUBUTTON:
  190.             if (val) {
  191.             unqdevice(TIMER0);
  192.             switch (dopup(menu)) {
  193.                 case 1:
  194.                 system("ical");
  195.                 break;
  196.                 case 2:
  197.                 alarmflag = !alarmflag;
  198.                 setpup(menu, 2,
  199.                      alarmflag ? PUP_CHECK : PUP_BOX);
  200.                 if (alarmflag) {
  201.                     ahour = 12;
  202.                     aminute = 0;
  203.                 }
  204.                 break;
  205.             }
  206.             qdevice(TIMER0);
  207.             draw_needed = TRUE;
  208.             }
  209.             break;
  210.         }
  211.     }
  212.     if (leftdown && alarmflag)
  213.         setalarmangle(mousex,mousey);
  214.     makeface();
  215.     draw_needed = FALSE;
  216.     }
  217. }
  218.  
  219. void
  220. setalarmangle(long mousex,long mousey)
  221. {
  222.     float ratio,angle;
  223.     long mx,my;
  224.     mx = mousex - width/2 - xoffset;
  225.     my = mousey - height/2 - yoffset;
  226.     if (mx==0 && my==0)
  227.     return;
  228.     if (abs(mx)>abs(my)) {
  229.     ratio = (float)my / (float)mx;
  230.     angle = (float)atan(ratio) * ANGCONV;
  231.     if (mx>0) {
  232.         angle = 3.0 - angle;
  233.     } else {
  234.         angle = 9.0 - angle;
  235.     }
  236.     } else {
  237.     ratio = (float)mx/(float)my;
  238.     angle = (float)atan(ratio) * ANGCONV;
  239.     if (my>0) ;
  240.     else angle = 6.0 + angle;
  241.     }
  242.     ahour = (int)angle;
  243.     aminute = (int)(0.5 + 60*(angle - ahour));
  244.     while (aminute<0) {
  245.     ahour --;
  246.     aminute += 60;
  247.     }
  248.     while (aminute>59) {
  249.     ahour ++;
  250.     aminute -= 60;
  251.     }
  252.     while (ahour<1) {
  253.     ahour += 12;
  254.     }
  255.     while (ahour>12) {
  256.     ahour -= 12;
  257.     }
  258. }
  259.  
  260. int
  261. shouldbeep()
  262. {
  263.     long t1,t2;
  264.     if (!alarmflag)
  265.         return 0;
  266.     t1 = (hours%12)*60 + minutes;
  267.     t2 = (ahour%12)*60 + aminute;
  268.     return (t1-t2>=0 && t1-t2<5);
  269. }
  270.  
  271. void setOrtho()
  272. {
  273.     float sc;
  274.  
  275.     if (iconic) {
  276.     if (width > height) {
  277.         sc = 100.0 / height;
  278.         ortho2(-width * sc , width * sc, -100.0, 100.0);
  279.     } else {
  280.         sc = 100.0 / width;
  281.         ortho2(-100.0, 100.0, -height * sc, height * sc);
  282.     }
  283.     } else {
  284.     ortho2(-100.0,100.0,-100.0,100.0);
  285.     }
  286. }
  287.  
  288. void
  289. makeface()
  290. {
  291.     register int i;
  292.  
  293.     setOrtho();
  294.     gettime(&hours,&minutes,&seconds);
  295.     if (shouldbeep() && !seconds)
  296.     ringbell();
  297.  
  298.     if (doaa) {
  299.     /* clear to a black background */
  300.     cpack(0);
  301.     clear();
  302.  
  303.     /* enable antialiasing of polygons */
  304.     polysmooth(PYSM_ON);
  305.     blendfunction(BF_MIN_SA_MDA,BF_ONE);
  306.  
  307.     pushmatrix();
  308.         scale(8.0,8.0,1.0);
  309.         pushmatrix();
  310.  
  311.         /* draw dot */
  312.         if (dodot) {
  313.             setcolor(GREEN);
  314.             drawcircle(2.0);
  315.         }
  316.  
  317.         /* draw the hands */
  318.         showhands(greyindex(0.4),greyindex(0.9),FALSE);
  319.  
  320.         /* draw the shadows */
  321.         pushmatrix();
  322.             translate(0.60,-0.60,0.0);
  323.             if (dodot) {
  324.             setgrey(0.0);
  325.             drawcircle(2.0);
  326.             }
  327.             showhands(greyindex(0.1),greyindex(0.1),TRUE);
  328.         popmatrix();
  329.  
  330.         /* draw the markers */
  331.         setgrey(0.8);
  332.         for (i=0; i<12; i++) {
  333.             if (i==0)
  334.             rectf(-0.5,9.0,0.5,11.0);
  335.             else if (i==3 || i==6 || i== 9)
  336.             rectf(-0.5,9.5,0.5,10.5);
  337.             else
  338.             rectf(-0.25,9.5,0.25,10.5);
  339.             rotate(-300,'z');
  340.         }
  341.         popmatrix();
  342.     popmatrix();
  343.  
  344.     /* clear the background */
  345.     if (shouldbeep())
  346.         setcolor(RED);
  347.     else
  348.         setgrey(0.2);
  349.     rectf(-100.0,-100.0,100.0,100.0);
  350.  
  351.     polysmooth(PYSM_OFF);
  352.     blendfunction(BF_ONE,BF_ZERO);
  353.  
  354.     swapbuffers();
  355.     }
  356.     else {
  357.     pushmatrix();
  358.         if (shouldbeep()) 
  359.         setcolor(RED);
  360.         else 
  361.         setgrey(0.2);
  362.         clear();
  363.         scale(8.0,8.0,1.0);
  364.         pushmatrix();
  365.         setgrey(0.8);
  366.         for (i=0; i<12; i++) {
  367.             if (i==0)
  368.             rectf(-0.5,9.0,0.5,11.0);
  369.             else if (i==3 || i==6 || i== 9)
  370.             rectf(-0.5,9.5,0.5,10.5);
  371.             else
  372.             rectf(-0.25,9.5,0.25,10.5);
  373.             rotate(-300,'z');
  374.         }
  375.         pushmatrix();
  376.             translate(0.60,-0.60,0.0);
  377.             showhands(greyindex(0.1),greyindex(0.1),TRUE);
  378.             if (dodot) {
  379.             setgrey(0.0);
  380.             drawcircle(2.0);
  381.             }
  382.         popmatrix();
  383.         showhands(greyindex(0.4),greyindex(0.9),FALSE);
  384.         if (dodot) {
  385.             setcolor(GREEN);
  386.             drawcircle(2.0);
  387.         }
  388.         popmatrix();
  389.     popmatrix();
  390.     }
  391. }
  392.  
  393. void
  394. showhands(int fillcolor,int bordercolor,int shadow)
  395. {
  396.     if (doaa) {
  397.     /* draw the second hand */
  398.     pushmatrix();
  399.         rotate(-seconds*3600/60,'z');
  400.         setcolor(bordercolor); 
  401.         drawpolf2(4,sechand);
  402.     popmatrix();
  403.  
  404.     /* draw the minute hand */
  405.     pushmatrix();
  406.         rotate(-(minutes*3600/60)-(seconds),'z');    
  407.         pushmatrix();
  408.         scale(0.75,0.75,0.75);
  409.         setcolor(fillcolor); 
  410.         drawpolf2(4,minhand);
  411.         popmatrix();
  412.         setcolor(bordercolor);
  413.         drawpolf2(4,minhand);
  414.     popmatrix();
  415.  
  416.     /* draw the hour hand */
  417.     pushmatrix();
  418.         rotate(-(hours*3600/12)-(minutes*5),'z');
  419.         pushmatrix();
  420.         scale(0.75,0.75,0.75);
  421.         setcolor(fillcolor); 
  422.         drawpolf2(4,hourhand);
  423.         popmatrix();
  424.         setcolor(bordercolor);
  425.         drawpolf2(4,hourhand);
  426.     popmatrix();
  427.  
  428.     /* draw the alarm hand and time */
  429.     if (alarmflag) {
  430.         static char timestring[20];
  431.         /* draw the alarm hand */
  432.         pushmatrix();
  433.         rotate(-(ahour*3600/12)-(aminute*5),'z');
  434.         if (shadow)
  435.             setgrey(0.1);
  436.         else setcolor(RED);
  437.         drawpolf2(4,alrmhand);
  438.         popmatrix();
  439.         if (!iconic) {
  440.         /* draw the alarm time */
  441.         ortho2(0.,(float)width,0.,(float)height);
  442.         pushmatrix();
  443.             loadmatrix(ident);
  444.             setcolor(YELLOW);
  445.             sprintf(timestring,"%2d:%2d",ahour,aminute);
  446.             if (aminute<10)
  447.             timestring[3] = '0';
  448.             cmov2i(width/2 - strwidth(timestring)/2,getheight()/2);
  449.             charstr(timestring);
  450.         popmatrix();
  451.         setOrtho();
  452.         }
  453.     }
  454.     } else {
  455.     /* draw the alarm hand and time */
  456.     if (alarmflag) {
  457.         static char timestring[20];
  458.         /* draw the alarm hand */
  459.         pushmatrix();
  460.         rotate(-(ahour*3600/12)-(aminute*5),'z');
  461.         if (shadow) 
  462.             setgrey(0.1);
  463.         else 
  464.             setcolor(RED);
  465.         drawpolf2(4,alrmhand);
  466.         drawpoly2(4,alrmhand);
  467.         popmatrix();
  468.         if (!iconic) {
  469.         /* draw the alarm time */
  470.         ortho2(0.,(float)width,0.,(float)height);
  471.         pushmatrix();
  472.             loadmatrix(ident);
  473.             setcolor(YELLOW);
  474.             sprintf(timestring,"%2d:%2d",ahour,aminute);
  475.             if (aminute<10)
  476.             timestring[3] = '0';
  477.             cmov2i(width/2 - strwidth(timestring)/2,getheight()/2);
  478.             charstr(timestring);
  479.         popmatrix();
  480.         setOrtho();
  481.         }
  482.     }
  483.  
  484.     /* draw the hour hand */
  485.     pushmatrix();
  486.         rotate(-(hours*3600/12)-(minutes*5),'z');
  487.         setcolor(fillcolor); 
  488.         drawpolf2(4,hourhand);
  489.         setcolor(bordercolor);
  490.         drawpoly2(4,hourhand);
  491.     popmatrix();
  492.  
  493.     /* draw the minute hand */
  494.     pushmatrix();
  495.         rotate(-(minutes*3600/60)-(seconds),'z');    
  496.         setcolor(fillcolor); 
  497.         drawpolf2(4,minhand);
  498.         setcolor(bordercolor);
  499.         drawpoly2(4,minhand);
  500.     popmatrix();
  501.  
  502.     /* draw the second hand */
  503.     pushmatrix();
  504.         rotate(-seconds*3600/60,'z');
  505.         setcolor(fillcolor); 
  506.         drawpolf2(4,sechand);
  507.         setcolor(bordercolor);
  508.         drawpoly2(4,sechand);
  509.     popmatrix();
  510.  
  511.     /* draw a point at the center */
  512.     pnt(0.0,0.0,0.0);
  513.     }
  514. }
  515.  
  516. void
  517. gettime(int * h,int * m,int * s )
  518. {
  519.     long clock;
  520.     struct tm *timeofday;
  521.  
  522.     time(&clock);
  523.     timeofday = (struct tm *)localtime(&clock);
  524.     *h = timeofday->tm_hour;
  525.     *m = timeofday->tm_min;
  526.     *s = timeofday->tm_sec;
  527. }
  528.  
  529. void
  530. setcolor(int c)
  531. {
  532.     if (!doaa)
  533.     color(c);
  534.     else {
  535.     switch (c) {
  536.     case BLACK:
  537.         cpack(0xff000000);
  538.         break;
  539.     case RED:
  540.         cpack(0xff0000ff);
  541.         break;
  542.     case GREEN:
  543.         cpack(0xff00ff00);
  544.         break;
  545.     case YELLOW:
  546.         cpack(0xff00ffff);
  547.         break;
  548.     default:
  549.         if ((c >= 32) && (c <= 56)) {
  550.         int val;
  551.         val = (c-32)*10;
  552.         cpack(val + (val<<8) + (val<<16) + 0xff000000);
  553.         } else {
  554.         fprintf(stderr,"setcolor: unexpected value %d\n",c);
  555.         exit(1);
  556.         }
  557.         break;
  558.     }
  559.     }
  560. }
  561.  
  562. void
  563. drawpoly2(long verts, XY* v)
  564. {
  565.     register i;
  566.     bgnclosedline();
  567.     for (i=0; i<verts; i++, v++) {
  568.     v2f(&v->x);
  569.     }
  570.     endclosedline();
  571. }
  572.  
  573. void
  574. drawpolf2(long verts, XY* v)
  575. {
  576.     register i;
  577.     bgnpolygon();
  578.     for (i=0; i<verts; i++, v++) {
  579.     v2f(&v->x);
  580.     }
  581.     endpolygon();
  582. }
  583.  
  584. #define CIRCVERTS 80
  585.  
  586. void
  587. drawcircle(float radius)
  588. {
  589.     static n = 0;
  590.     static float *data;
  591.     register i;
  592.     register float *p;
  593.  
  594.     /* create data structure if not already computed */
  595.     if (n != CIRCVERTS) {
  596.     if (n)
  597.         free(data);
  598.     data = (float*)malloc(sizeof(float)*2*(CIRCVERTS+1));
  599.     n = CIRCVERTS;
  600.     data[0] = data[1] = 0;
  601.     for (i=0; i<CIRCVERTS; i++) {
  602.         data[2*(i+1)] = radius * fcos(i*2*M_PI / CIRCVERTS);
  603.         data[2*(i+1)+1] = radius * fsin(i*2*M_PI / CIRCVERTS);
  604.     }
  605.     }
  606.  
  607.     /* draw the circle as a single triangle mesh */
  608.     bgntmesh();
  609.     p = data;
  610.     v2f(p);
  611.     p += 2;
  612.     for (i=0; i<CIRCVERTS; i++) {
  613.     v2f(p);
  614.     p += 2;
  615.     swaptmesh();
  616.     }
  617.     v2f(data+2);
  618.     endtmesh();
  619. }
  620.